package com.gateway.filter;

import com.common.utils.CookieUtils;
import com.gateway.service.UserService;
import com.gateway.uti.WebUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * @author Elias
 * @version 1.0
 * @date 2021-06-16 16:10
 * @description
 * @copyright 2021
 */
@Component
@ConfigurationProperties(prefix = "custom.uri")
public class PermissionCheck extends ZuulFilter {

  private UserService userService;
  /** 需要鉴权的路径及需要的权限等级 */
  @Value("#{${custom.uri.check}}")
  private Map<String, Integer> uriCheck;
  /** 直接禁止的路径 */
  @Value("#{'${custom.uri.forbidden}'.split(',')}")
  private List<String> uriForbidden;

  @Override
  public String filterType() {
    return "pre";
  }

  @Override
  public int filterOrder() {
    return 0;
  }

  /**
   * 如果路径包含在鉴权列表中，则进入鉴权逻辑
   *
   * @return 路径是否在鉴权列表中
   */
  @Override
  public boolean shouldFilter() {
    RequestContext context = RequestContext.getCurrentContext();
    HttpServletRequest request = context.getRequest();
    String uri = request.getRequestURI();
    uri = WebUtils.removeExtraSlashOfUrl(uri);
    return uriCheck.containsKey(uri) || uriForbidden.contains(uri);
  }

  /**
   * 鉴权逻辑
   *
   * @return
   * @throws ZuulException
   */
  @Override
  public Object run() throws ZuulException {
    RequestContext context = RequestContext.getCurrentContext();
    HttpServletRequest request = context.getRequest();
    HttpServletResponse response = context.getResponse();
    String uri = request.getRequestURI();
    uri = WebUtils.removeExtraSlashOfUrl(uri);
    if (uriForbidden.contains(uri)) {
      //            禁止访问地址
      response.setContentType("text/html; charset=UTF-8");
      context.setSendZuulResponse(false);
      context.setResponseStatusCode(401);
      context.setResponseBody("无权访问");
      return null;
    } else if (uriCheck.containsKey(uri)) {
      //            需要鉴权
      String ticket = CookieUtils.getCookieValue(request, "EM_TICKET", true);
      Integer userType = userService.queryUserType(ticket);
      if (userType == null || userType < uriCheck.get(uri)) {
        //                越权访问
        response.setContentType("text/html; charset=UTF-8");
        context.setSendZuulResponse(false);
        context.setResponseStatusCode(401);
        context.setResponseBody("无权访问");
      }
      return null;
    } else {
      //            无需鉴权
      return null;
    }
  }
}
